package uk.ac.strath.cis.metric_spaces.distance;

import uk.ac.strath.cis.collections.Point;
import uk.ac.strath.cis.collections.Point.PointImpl;
import uk.ac.strath.cis.metric_spaces.framework.Distance;

public class StructuralEntropicPointDistance extends PointDistance{

	private double sum1;
	private double sum2;

	public double distance(Point p1, Point p2) {
		sum1 = sum(p1);
		sum2 = sum(p2);	
		double res = 2 * super.distance(p1, p2) - 1;
		res = Math.pow(res, 0.48);
		return  res;
		
	}

	private double sum(Iterable<Double> e1) {
		double sum = 0.0;
		for(double d : e1){
			sum += d;
		}
		return sum;
	}
	
	@Override
	protected double accumulator() {
		return 1.0;
	}

	@Override
	protected double algorithm(double acc, double a, double b) {
		if(a != 0.0 && b != 0.0){
			double p_a = a / sum1;
			double p_b = b / sum2;
			double sum_p = p_a + p_b;
			double u = p_a / sum_p;
			double v = p_b / sum_p;
			double w = sum_p / 2;
			acc *= Math.pow(u, u * w) * Math.pow(v, v * w);
		}
		return acc;
	}
	
	public static void main(String[] args) {
		Point a = PointImpl.create(1.0,1.0,1.0);
		Point b = PointImpl.create(1.0,2.0,3.0);
		Distance<Point> d = new StructuralEntropicPointDistance();
		System.out.println(d.distance(a, b));
		
	}

}
